import {withLock} from "easylock";
import {getSkuId} from "../../../api/utils";
import {ProductModel} from "../../../database/models/Product";
import {StockRecordModel} from "../../../database/models/stockRecord";
import {searchAry} from "../../../utils/search";

export const typeDefs = `

 type OtherPrice {
   jd: Float
   tmall:Float,
   kaola: Float,
 }

 input InputOtherPrice {
   jd: Float
   tmall:Float,
   kaola: Float
 }

 type Product{
   _id:String!
   skuId: String!

   category: String!
   brand: String!
   series: String!
   name: String!
   authorized: Boolean!
   state: String!
   onPointMarket: Boolean!
   pointPrice: Int!
   pointRedeem: Int!
   trackId: String
   model: String!

   gram: Float!
   stock: Int!
   wrap: String!
   expireAt: String!

   coverUrl: String!
   description:String!
   marketPrice: Float!
   underLinePrice: Float!
   promotePrice: Float!
   otherPrice: OtherPrice

   tag: String

   createAt: String!
   updateAt: String!
   sortNum: Int!
 }

 input ProductInput{
   category: String!
   brand: String!
   series: String!
   name: String!
   authorized: Boolean!
   state: String!
   onPointMarket: Boolean!
   pointPrice: Int!
   pointRedeem: Int!
   trackId: String
   model: String!

   gram: Float!
   stock: Int!
   wrap: String!
   expireAt: String!
   createAt: String
   updateAt: String!
   coverUrl: String!
   description:String!
   marketPrice: Float!
   underLinePrice: Float!
   promotePrice: Float!
   otherPrice: InputOtherPrice
   tag: String
   sortNum: Int!
 }

  input ProductUpdateInput{
   category: String!
   brand: String!
   series: String!
   name: String!
   authorized: Boolean!
   state: String!
   onPointMarket: Boolean!
   pointPrice: Int!
   pointRedeem: Int!
   trackId: String
   model: String!

   gram: Float!
   stock: Int!
   wrap: String!
   expireAt: String!
   createAt: String
   coverUrl: String!
   description:String!
   marketPrice: Float!
   underLinePrice: Float!
   promotePrice: Float!
   otherPrice: InputOtherPrice

   tag: String
   updateAt: String!
   sortNum: Int!
 }
`

export const queryDefs = `
  products(page:Int,size:Int): [Product]!
  product(_id: String!): Product
  searchProducts(query:String!): [Product]!
`

export const mutationDefs = `
 createProduct(p:ProductInput): Product
 offStockProduct(_id:String!): Product
 onStockProduct(_id:String!): Product
 deleteProduct(_id:String!): Boolean
 updateProduct(_id: String!, product:ProductUpdateInput!): Product
 setProductStock(_id: String, amount:Int!,note:String!): Product
`

export const resolvers = {

  Query: {
    product: async (_, {_id}) => {
      return ProductModel.findById(_id)
    },

    products: async (_, {page = 0, size = 20}) => {
      const ps = await ProductModel.find().sort({
        sortNum: -1, createAt: -1
      })
        // .skip(page * size).limit(size).lean()
      return ps
    },
    searchProducts: async (_, {query}) => {
      const ps = await ProductModel.find().lean()
      const reg = new RegExp(query, `i`)
      const rlt = searchAry(ps, reg)
      return rlt
    }
  },

  Mutation: {
    createProduct: async (_, product) => {
      const expireAt = new Date(product.p.expireAt)
      if (product.stock <= 0) {
        product.state = `off`
      }
      const p = new ProductModel({...product.p, createAt: new Date(), updateAt: new Date(), expireAt})
      p.skuId = getSkuId(p)
      await p.save()
      return p
    },
    async setProductStock(_, {_id, amount, note}) {

      return withLock(`product_${_id}`, async () => {

        if (amount < 0) {
          throw Error('错误的库存修改')
        }

        await StockRecordModel.create({product: _id, amount, note})
        return ProductModel.updateOne({_id}, {$set: {stock: amount}}, {new: true})
      })
    },

    offStockProduct: async (_, {_id}) => {
      return ProductModel.findByIdAndUpdate({_id}, {$set: {state: "off"}}, {new: true})
    },
    onStockProduct: async (_, {_id}) => {
      const product = await ProductModel.findById(_id)
      if (product.stock <= 0) {
        product.state = `off`
        throw Error(`无库存，已自动下架`)
      }
      return await ProductModel.findByIdAndUpdate({_id}, {$set: {state: "on"}}, {new: true})
    },
    deleteProduct: async (_, {_id}) => {
      return await ProductModel.deleteOne({_id})
    },
    updateProduct: async (_, {_id, product}) => {
      const expireAt = new Date(product.expireAt)
      if (product.stock <= 0) {
        product.state = `off`
      }
      const updatedProduct = await ProductModel.findByIdAndUpdate(_id, {
        ...product,
        expireAt,
        updateAt: new Date()
      }, {new: true})

      return updatedProduct
    }
  },
}
